package com.step.scene.camera;

import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLU;
import android.opengl.Matrix;

import com.step.Step;
import com.step.Step.Dimension;
import com.step.math.Vector;

/**
 * 欧拉相机（第一人称视角）
 * @author heop
 *
 */
public class EulerCamera extends Camera{
	final Vector position = new Vector(Dimension.d3d);
	float yaw;
	float pitch;
	float viewField;
	float aspectRatio;
	float near;
	float far;
	
	public EulerCamera(){
		this(67, Step.aspectRatio, 1, 100);
	}
	
	/**
	 * 创建第一人称相机
	 * @param viewField 视野范围（角度）
	 * @param aspectRatio 视窗长宽比
	 * @param near 近点剪裁平面
	 * @param far 远点裁剪平面
	 */
	public EulerCamera(float viewField, float aspectRatio, float near, float far) {
		super(CameraType.EULER_CAMERA);
		this.viewField = viewField;
		this.aspectRatio = aspectRatio;
		this.near = near;
		this.far = far;
	}

	/**
	 * 设置欧拉角
	 * @param yaw 左右偏转角度（与ｙ轴夹角）
	 * @param pitch 上下俯仰角度（与ｘ轴夹角）
	 */
	public void setAngles(float yaw, float pitch){
		setYaw(yaw);
		setPitch(pitch);
	}
	
	/**
	 * 旋转相机
	 * @param yawInc 左右偏转角增量
	 * @param pitchInc 上下俯仰角增量
	 */
	public void rotate(float yawInc, float pitchInc){
		this.yaw += yawInc;
		this.pitch += pitchInc;
		
		if(pitch < -90) pitch = -90;
		if(pitch > 90) pitch = 90;
	}
	
	@Override
	public void updateFrustum(GL10 gl) {
		gl.glViewport(0, 0, Step.renderer.getWidth(), Step.renderer.getHeight());
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glLoadIdentity();
		GLU.gluPerspective(gl, viewField, aspectRatio, near, far);
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
		
		gl.glRotatef(-pitch, 1, 0, 0);
		gl.glRotatef(-yaw, 0, 1, 0);
		gl.glTranslatef(-position.getX(), -position.getY(), -position.getZ());
	}

	final float[] matrix = new float[16];
	final float[] inVec = { 0, 0, -1, 1 };
	final float[] outVec = new float[4];
	final Vector direction = new Vector(Dimension.d3d);
	
	/**
	 * 获取相机朝向（方向向量），通过缩放该向量的值，让相机沿着该方向移动。
	 * @return
	 */
	public Vector getDirection() {
		Matrix.setIdentityM(matrix, 0);
		Matrix.rotateM(matrix, 0, yaw, 0, 1, 0);
		Matrix.rotateM(matrix, 0, pitch, 1, 0, 0);
		Matrix.multiplyMV(outVec, 0, matrix, 0, inVec, 0);
		direction.set(outVec[0], outVec[1], outVec[2]);
		return direction;
	}

	public float getYaw() {
		return yaw;
	}

	/**
	 * 设置相机绕ｙ轴旋转的角度，即左右偏转角度
	 * @param yaw
	 */
	public void setYaw(float yaw) {
		this.yaw = yaw;
	}

	public float getPitch() {
		return pitch;
	}

	/**
	 * 设置相机绕ｘ轴旋转的角度，即上下偏转角度（-90到90之间）
	 * @param pitch
	 */
	public void setPitch(float pitch) {
		if(pitch < -90){
			pitch = -90;
		}
		if(pitch > 90){
			pitch = 90;
		}
		this.pitch = pitch;
	}

	public Vector getPosition() {
		return position;
	}
}
